package com.reeygu.base;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

class ReadWriteResources {
    // volatile 类似于 synchronized 的轻量版
    private volatile Map<String, String> map = new HashMap<>();
    //创建读写锁
    private ReadWriteLock rwLock = new ReentrantReadWriteLock();

    //写数据
    public void put(String key, String value) {
        //先上锁
        rwLock.writeLock().lock();
        try {
            System.out.println("线程" + key + "正在写数据...");
            map.put(key, value);
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("线程" + key + "写完数据!");
            rwLock.writeLock().unlock();
        }
    }

    //读数据
    public String get(String key) {
        //先上锁
        rwLock.readLock().lock();
        String result = "";
        try {
            System.out.println("线程" + key + "正在读数据...");
            result = map.get(key);
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("线程" + key + "读完数据!");
            rwLock.readLock().unlock();
        }
        return result;
    }
}

public class ReadWriteLockDemo {
    public static void main(String[] args) {
        ReadWriteResources resources = new ReadWriteResources();
        //5个线程执行写操作
        for (int i = 0; i < 10; i++) {
            String num = String.valueOf(i);
            new Thread(() -> {
                System.out.println("线程" + Thread.currentThread().getName() + "写入数据：" + num);
                resources.put(num, num);
            }, num).start();
        }
        //5个线程执行读操作，正常来说，需要写完才能读
        for (int i = 0; i < 10; i++) {
            String num = String.valueOf(i);
            new Thread(() -> {
                System.out.println("线程" + Thread.currentThread().getName() + "读到的结果：" + resources.get(num));
            }, num).start();
        }
    }
}
